package ccm.component.oscilloscope;

import ccm.common.Crc;
import ccm.common.DataNotMatchException;
import ccm.common.ReceiveDataEvent;
import ccm.common.ReceiveDataListener;

import java.util.ArrayList;
import java.util.Arrays;

public class VisualScopeDataManager implements OscilloscopeDataManager, ReceiveDataListener
{
    /**
     * 用于保存接收到的数据
     */
    protected final ArrayList<float[]> data;
    protected final ArrayList<Long>    timeUs;

    /**
     * 接收缓冲
     */
    protected int[]   receiveBuf;
    /**
     * 接收缓冲起始
     */
    protected int     receiveBufStart;
    /**
     * 接收缓冲是否满了
     */
    protected boolean receiveBufFull;

    public VisualScopeDataManager()
    {
        receiveBuf     =new int[10];
        receiveBufStart=0;
        data           =new ArrayList<>(1024*128);
        timeUs         =new ArrayList<Long>(1024*128);
    }

    /**
     * 获取一共有几列
     *
     * @return 列数
     */
    public int getDataColumn()
    {
        return 4;
    }

    /**
     * 清空数据
     */
    synchronized public void clear()
    {
        data.clear();
        timeUs.clear();
    }

    /**
     * 获取数据行数
     */
    synchronized public int getDataLength()
    {
        if(data.size()!=timeUs.size())
            throw new DataNotMatchException();
        return data.size();
    }

    /**
     * 获取列的名字
     *
     * @param column 列
     * @return 注释
     */
    public String getColumnName(int column)
    {
        return String.format("Data%d",column+1);
    }

    /**
     * 获取第i行数据第column列是不是可用的数据点
     *
     * @param i      数据行
     * @param column 数据列
     * @return 是否可用
     */
    public boolean isColumnEnabled(int i,int column)
    {
        return true;
    }


    /**
     * 获取纵坐标
     *
     * @param i      数据行
     * @param column 数据列
     * @return 纵坐标
     */
    public float getY(int i,int column)
    {
        return data.get(i)[column];
    }

    public long getTimeUs(int i)
    {
        return timeUs.get(i);
    }


    /**
     * 克隆管理器
     *
     * @return 克隆的管理器
     */
    synchronized public VisualScopeDataManager clone()
    {
        try
        {
            return (VisualScopeDataManager)super.clone();
        }catch(CloneNotSupportedException ex)
        {
            ex.printStackTrace();
        }
        return null;
    }

    /**
     * 接收到数据事件
     */
    synchronized public void receiveData(ReceiveDataEvent event)
    {
        for(byte datum: event.getData())
        {
            receiveBuf[receiveBufStart]=Byte.toUnsignedInt(datum);
            ++receiveBufStart;
            if(receiveBufStart>=receiveBuf.length)
            {
                receiveBufFull =true;
                receiveBufStart=0;
            }
            if(crcCheck())
            {
                float[] ans=new float[4];
                for(int i=0;i<4;++i)
                    ans[i]=(short)(((receiveBuf[(i*2+receiveBufStart)%receiveBuf.length]&0XFF)|((receiveBuf[(i*2+1+receiveBufStart)%receiveBuf.length]&0XFF)<<8))&0XFFFF);
                data.add(ans);
                timeUs.add(event.getTimeUs());
                receiveBufStart=0;
                receiveBufFull =false;
                Arrays.fill(receiveBuf,0);
            }
        }
    }

    /**
     * 对数据缓存区域进行CRC校验
     *
     * @return true表示通过校验
     * false表示未通过校验
     */
    synchronized private boolean crcCheck()
    {
        if(!receiveBufFull)
            return false;
        int ans=(((receiveBuf[(8+receiveBufStart)%receiveBuf.length]&0XFF)|((receiveBuf[(9+receiveBufStart)%receiveBuf.length]&0XFF)<<8))&0XFFFF);
        return Crc.crc16Modbus(receiveBuf,receiveBufStart,8)==ans;
    }
}
